Lambda Python3.6でTweetしてみた[with Serverless Framework]
こんにちは、臼田です。
皆さん、Lambdaしてますか?
今回はLambdaでPython3.6を利用してツイッターにTweetしてみます。
私の目的としては、下記Step Functionsを利用したCVE Listのアップデート確認ですが、
Tweetの機能だけなら汎用的に利用できると思うので、汎用的な手順として書いていきます。
目次
- Twitterでアプリケーションを登録
- スクリプト作成
- Serverless Framework環境作成
- デプロイ
1. Twitterでアプリケーションを登録
ツイッターへの投稿には、利用するアカウントでアプリケーションを作成して、アプリケーション経由でAPIをリクエストする必要があります。
アプリケーション作成
ツイートしたいアカウントでログインして、TwitterのDeveloperサイトにアクセスします。
ページ最下部のTools「Manage my apps」からアプリケーションの管理ページへ移動します。
「Create New App」をクリックしてアプリケーションを作成します。
適当に情報を入力し「Create your Twitter application」をクリックします。
これでアプリケーションの作成が完了しました。
API Keyの取得
アプリケーション管理画面から「Keys and Access Tokens」タブに移動し、「Consumer Secret (API Secret)」及び「Consumer Secret (API Secret)」を控えます。
Access Tokenの取得
「Keys and Access Tokens」タブ下方へスクロールし、「Create my access token」をクリックします。
作成された「Access Token」及び「Access Token Secret」を控えます。
これでTwitter側の準備は完了です。
2. スクリプト作成
ローカル環境でスクリプトを作成します。
環境準備
今回はPython 3.6で用意しますので、私の場合は作業用に作成したフォルダでpyenv localで個別の環境を割り当てています。
$ pyenv virtualenv 3.6.1 tweet_3.6.1 $ pyenv local tweet_3.6.1 $ python --version Python 3.6.1
パッケージがglobalの環境と混ざらないように分けたい場合には、下記を参考に専用の環境を作成することをおすすめします。
Tweepyインストール
Twitter APIを利用するには、OAuth2.0を利用した認可が必要になります。
OAuth2.0のパッケージを利用してもいいのですが、Twitter APIに最適化したパッケージがいくつかあるのでそちらを利用します。
今回は、Tweepyを利用してみます。
$ pip install tweepy
スクリプト作成
今回は下記のように作成しました。
# tweet.py # -*- coding: utf-8 -*- import os import tweepy def lambda_handler(event, context): consumer_key = os.environ['TW_CONSUMER_KEY'] consumer_secret = os.environ['TW_CONSUMER_SECRET'] access_token = os.environ['TW_ACCESS_TOKEN'] access_token_secret = os.environ['TW_ACCESS_TOKEN_SECRET'] auth = tweepy.OAuthHandler(consumer_key, consumer_secret) auth.set_access_token(access_token, access_token_secret) api = tweepy.API(auth) r = api.update_status(event['message']) return 0 # call lambda_handler if __name__ == "__main__": import sys import json lambda_handler(json.loads(sys.argv[1]), {})
本当はエラー処理とか入れたほうがいいですが、とりあえずこれで動きます。
API Key等はハードコーディングしないように環境変数から取るようにしています。
Lambdaは環境変数に対応しているので、このやり方でもいいですし、引数で渡したりS3のjson読みに行ったりしてもいいですが、環境変数だとServerless Frameworkの中で値を管理できます。
tweetする内容は引数で取るようにしています。
末尾はローカルのターミナルから実行する際に引数をlambda_handlerに渡して実行するように指定しています。
環境変数の設定
ローカルでテストするために環境変数の設定をします。
export TW_CONSUMER_KEY=xxxxxxxxxxxxxxxx export TW_CONSUMER_SECRET=xxxxxxxxxxxxxxxx export TW_ACCESS_TOKEN=xxxxxxxxxxxxxxxx export TW_ACCESS_TOKEN_SECRET=xxxxxxxxxxxxxxxx
ローカルからの投稿
試しにローカルから実行してみます。
メッセージはjsonの"message"キーに入れて渡します。
$ python tweet.py '{"message":"test tweet from local"}'
無事投稿できました。
3. Serverless Framework環境作成
スクリプトが作成できたので、Serverless Frameworkを利用してLambdaにデプロイできるようにします。
Serverless Frameworkの導入については下記をご参考にして下さい。
なお、今回のバージョン(1.18.0)ではnode.jsは「v6.5.0」が求められます。(参考)
serverless-python-requirementsの導入
LambdaでPythonの外部モジュールを利用する場合には、Zipでまとめてアップロードする必要がありますが、serverless-python-requirementsというプラグインを利用すると、デプロイ時に自動的に必要なプラグインをまとめてアップロードしてくれます。
詳しくは下記を参照して下さい。
私の環境は以下のようになっています。
$ node -v v6.11.1 $ sls --version 1.18.0 $ npm ls | grep serverless-python-requirements └─┬ serverless-python-requirements@2.4.1
サービスの作成
Serverless Frameworkでサービスを作成します。
既存のフォルダで作成するので下記のようになります。
$ sls create -t aws-python3 -n tweet
serverless.ymlを変更します。
service: tweet provider: name: aws runtime: python3.6 # you can overwrite defaults here region: us-west-2 memorySize: 128 timeout: 180 plugins: - serverless-python-requirements functions: tweet: handler: tweet.lambda_handler environment: TW_CONSUMER_KEY: xxxxxxxxxxxxxxx TW_CONSUMER_SECRET: xxxxxxxxxxxxxxx TW_ACCESS_TOKEN: xxxxxxxxxxxxxxx TW_ACCESS_TOKEN_SECRET: xxxxxxxxxxxxxxx custom: pythonRequirements: pythonBin: python
pluginとしてserverless-python-requirementsを読み込ませています。
また、関数名を適切に変更し、「environment」要素で環境変数を定義しています。
custom
部分は次で説明します。
index.jsの編集
serverless-python-requirementsの2.4.1では、残念ながらpyenv環境での実行に対応してません。
具体的には、serverless.yml
で設定したprovicer.runtime
の値をpythonのエイリアスとして使用しようとします。
したがって、LambdaでPython3.6を利用するには、環境上のPythonもpython3.6で呼び出されないとserverless-python-requirementsの2.4.1では正常に動作しません。
対応策として、実際に./node_modules/serverless-python-requirements/index.js
でprovicer.runtime
を読み込む部分(80行目ぐらい)を下記のように変更します。
// const runtime = this.serverless.service.provider.runtime; const runtime = this.serverless.service.custom.pythonRequirements.pythonBin;
これで、serverless.yml
で追記したcustom
の設定を読み込むようになります。
※pyenvで動作しない仕様についてはserverless-python-requirementsに修正を依頼しています
requirements.txtの作成
serverless-python-requirementsでまとめる外部モジュールを指定します。
# requirements.txt tweepy
4. デプロイ
それではsls deploy -v
でデプロイします。
デプロイが完了するとマネジメントコンソールのLambdaの画面で作成されていることが確認できます。
sls invoke local
コマンドで動作を確認してもいいですが、今回はマネジメントコンソールからテストしてみます。
テストの設定から下記のようにmessageを設定します。
実行すると、投稿が確認できました。
さいごに
これで、LambdaのPython3.6からツイッターにtweetできました。
serverless-python-requirementsの問題は少しありましたが、それ以外は比較的簡単に実行できる手順かと思います。
さて、次回はStep Functionsでこれまで作成したLambdaをつなげてみます。